package 双链表;

/**
 * @Description 双链表
 * 使用带 头指针 的双向链表实现 –水浒英雄排行榜
 * 管理单向链表的缺点分析:
 * 单向链表，查找的方向只能是一个方向，而双向链表可以向前或者向后查找。
 * 单向链表不能自我删除，需要靠辅助节点 ，而双向链表，则可以自我删除，
 * 所以前面我们单链表删除时节点，总是找到temp,
 * temp是待删除节点的前一个节点(认真体会). 确实方便了不少
 * @Author 俊昭
 * @Date 2022/4/27
 */
public class DoubleLinkedList {
    private final DNode head = new DNode(- 1, "", "");
    private final DNode tail = new DNode(9999999, "", "");

    // 增
    /**
     * @param newDNode 新的好汉对象
     * @description 增
     * 添加时，根据排名插入到指定位置 如果有这个排名，则添加失败，并给出提示
     * @author 俊昭
     * @date 2022/4/27
     */
    public void add(DNode newDNode) {
        if (head.next == null) {
            head.next = newDNode;
            newDNode.last = head;
            newDNode.next = tail;
            tail.last = newDNode;
        } else {
            DNode temp = head.next;
            while (temp != tail) {
                DNode t = temp.next;
                if (newDNode.No == temp.No) {
                    System.out.println("好汉已存在,请检查信息:" + " " + newDNode);
                    break;
                } else if (temp.next == tail) {
                    temp.next = newDNode;
                    newDNode.last = temp;
                    newDNode.next = tail;
                    tail.last = newDNode;
                    break;
                } else if (newDNode.No > temp.No && newDNode.No < temp.next.No) {
                    temp.next.last = newDNode;
                    newDNode.next = temp.next;
                    temp.next = newDNode;
                    newDNode.last = temp;
                    break;
                }
                temp = t;
            }
        }
    }

    /**
     * @param No 好汉排名
     * @description 删
     * 从链表中移除节点
     * 实现方式 使被删除的节点的前一个节点的nextNode指向下一个节点
     * 使被删除的节点的下一个节点指向被删除的节点前一个节点
     * @author 俊昭
     * @date 2022/4/27
     */
    public void del(int No) {
        if (head.next == null) {
            System.out.println("表中还未有信息");
        } else {
            DNode temp = head;
            while (temp != tail) {
                if (temp.next.No == No) {
                    System.out.println("删除成功 信息为:" + temp.next);

                    temp.next.next.last = temp;
                    temp.next = temp.next.next;

                    break;
                }
                temp = temp.next;
            }
            if (temp == tail) {

                System.out.println("您输入的好汉编号不存在，请检查");
            }
        }
    }

    /**
     * @param newNode 新的好汉对象
     * @description 改
     * 修改一个节点信息 编号不改变只改变信息
     * @author 俊昭
     * @date 2022/4/27
     */
    public void set(DNode newNode) {
        if (head.next == null) {
            System.out.println("表中还未有信息");
        } else {
            DNode temp = head.next;
            while (temp != tail) {
                if (temp.No == newNode.No) {
                    temp.name = newNode.name;
                    temp.desc = newNode.desc;
                    break;
                }
                temp = temp.next;
            }
            if (temp == tail) {
                System.out.println("您输入的好汉编号不存在，请检查");
            }
        }

    }

    /**
     * @param No 好汉排名
     * @description 查
     * 输入好汉排名 若有 打印其信息；无 给出提示。
     * @author 俊昭
     * @date 2022/4/27
     */
    public void get(int No) {
        if (head.next == null) {
            System.out.println("表中还未有信息");
        } else {
            DNode temp = head.next;
            while (temp != tail) {
                if (temp.No == No) {
                    System.out.print("找到排名" + No + "好汉信息:");
                    System.out.println(temp);
                    break;
                }
                temp = temp.next;
            }
            if (temp == tail) {
                System.out.println("未找到好汉信息");
            }

        }
    }

    /**
     * @description 展示(正序)
     * @author 俊昭
     * @date 2022/4/27
     */
    public void show() {
        if (head.next != null) {
            DNode temp = this.head;
            while (temp.next != tail) {
                temp = temp.next;
                System.out.println(temp);
            }
            System.out.println();
        } else {
            System.out.println("表中还未有信息");
        }
    }

    /**
     * @description 展示(逆序)
     * @author 俊昭
     * @date 2022/4/27
     */
    public void showReversed() {
        if (tail.last != null) {
            DNode temp = this.tail;
            while (temp.last != head) {
                temp = temp.last;
                System.out.println(temp);
            }
            System.out.println();
        } else {
            System.out.println("表中还未有信息");
        }
    }


}

class DoubleLinkedListTest {
    public static void main(String[] args) {
        DoubleLinkedList dll = new DoubleLinkedList();
//        增
        dll.add(new DNode(1, "宋江", "及时雨"));
        dll.add(new DNode(4, "公孙胜", "入云龙"));
        dll.add(new DNode(3, "吴用", "智多星"));
        dll.add(new DNode(2, "卢俊义", "玉麒麟"));
//        dll.add(new DNode(6, "林冲", "豹子头"));
        dll.add(new DNode(21, "刘唐", "赤发鬼"));
        dll.add(new DNode(14, "武松", "行者"));
        // 这条信息是错的 准备使用set方法修改
        dll.add(new DNode(13, "林冲", "豹子头"));
        dll.show();
        // 逆序打印
        dll.showReversed();

//        删
        dll.del(1);
        dll.del(3);
        dll.del(5);// 不存在的
        dll.show();
//        改
        dll.set(new DNode(13, "鲁智深", "花和尚"));
        dll.set(new DNode(6, "鲁智深", "花和尚"));

        dll.show();
//        查
        dll.get(4);


    }
}

class DNode {

    public int No;// 排行
    public String name;// 名字
    public String desc;// 描述

    public DNode next;// 下一个元素
    public DNode last;// 上一个元素

    public DNode(int no, String name, String desc) {
        No = no;
        this.name = name;
        this.desc = desc;
    }

    /**
     * 重写toString
     *
     * @return 返回一位英雄的各信息
     */
    @Override
    public String toString() {
        return "好汉{" +
                "排名 " + No +
                ", 姓名 " + name +
                ", 诨号 " + desc +
                '}';
    }
}